home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / xshp15.zip / DRAW.ASM < prev    next >
Assembly Source File  |  1991-09-29  |  7KB  |  157 lines

  1. ; Draws all pixels in the list of horizontal lines passed in, in
  2. ; mode X, the VGA's undocumented 320x240 256-color mode. Clips to
  3. ; the rectangle specified by (ClipMinX,ClipMinY),(ClipMaxX,ClipMaxY).
  4. ; Draws to the page specified by CurrentPageBase.
  5. ; C near-callable as:
  6. ;     void DrawHorizontalLineList(struct HLineList * HLineListPtr,
  7. ;          int Color);
  8. ;
  9. ; All assembly code tested with TASM 2.0 and MASM 5.0
  10.  
  11. SCREEN_WIDTH    equ     320
  12. SCREEN_SEGMENT  equ     0a000h
  13. SC_INDEX equ    03c4h   ;Sequence Controller Index
  14. MAP_MASK equ    2       ;Map Mask register index in SC
  15.  
  16. HLine   struc
  17. XStart  dw      ?       ;X coordinate of leftmost pixel in line
  18. XEnd    dw      ?       ;X coordinate of rightmost pixel in line
  19. HLine   ends
  20.  
  21. HLineList struc
  22. Lngth   dw      ?       ;# of horizontal lines
  23. YStart  dw      ?       ;Y coordinate of topmost line
  24. HLinePtr dw     ?       ;pointer to list of horz lines
  25. HLineList ends
  26.  
  27. Parms   struc
  28.                 dw      2 dup(?) ;return address & pushed BP
  29. HLineListPtr    dw      ?       ;pointer to HLineList structure
  30. Color           dw      ?       ;color with which to fill
  31. Parms   ends
  32.         .model small
  33.         .data
  34.         extrn   _CurrentPageBase:word,_ClipMinX:word
  35.         extrn   _ClipMinY:word,_ClipMaxX:word,_ClipMaxY:word
  36. ; Plane masks for clipping left and right edges of rectangle.
  37. LeftClipPlaneMask       db      00fh,00eh,00ch,008h
  38. RightClipPlaneMask      db      001h,003h,007h,00fh
  39.         .code
  40.         align   2
  41. ToFillDone:
  42.         jmp     FillDone
  43.         public _DrawHorizontalLineList
  44.         align   2
  45. _DrawHorizontalLineList proc
  46.         push    bp              ;preserve caller's stack frame
  47.         mov     bp,sp           ;point to our stack frame
  48.         push    si              ;preserve caller's register variables
  49.         push    di
  50.         cld                     ;make string instructions inc pointers
  51.         mov     dx,SC_INDEX
  52.         mov     al,MAP_MASK
  53.         out     dx,al           ;point SC Index to the Map Mask
  54.         mov     ax,SCREEN_SEGMENT
  55.         mov     es,ax   ;point ES to display memory for REP STOS
  56.         mov     si,[bp+HLineListPtr] ;point to the line list
  57.         mov     bx,[si+HLinePtr] ;point to the XStart/XEnd descriptor
  58.                                 ; for the first (top) horizontal line
  59.         mov     cx,[si+YStart]  ;first scan line to draw
  60.         mov     si,[si+Lngth]   ;# of scan lines to draw
  61.         cmp     si,0            ;are there any lines to draw?
  62.         jle     ToFillDone      ;no, so we're done
  63.         cmp     cx,[_ClipMinY]  ;clipped at top?
  64.         jge     MinYNotClipped  ;no
  65.         neg     cx              ;yes, discard however many lines are
  66.         add     cx,[_ClipMinY]  ; clipped
  67.         sub     si,cx           ;that many fewer lines to draw
  68.         jle     ToFillDone      ;no lines left to draw
  69.         shl     cx,1            ;lines to skip*2
  70.         shl     cx,1            ;lines to skip*4
  71.         add     bx,cx           ;advance through the line list
  72.         mov     cx,[_ClipMinY]  ;start at the top clip line
  73. MinYNotClipped:
  74.         mov     dx,si
  75.         add     dx,cx           ;bottom row to draw + 1
  76.         cmp     dx,[_ClipMaxY]  ;clipped at bottom?
  77.         jle     MaxYNotClipped  ;no
  78.         sub     dx,[_ClipMaxY]  ;# of lines to clip off the bottom
  79.         sub     si,dx           ;# of lines left to draw
  80.         jle     ToFillDone      ;all lines are clipped
  81. MaxYNotClipped:
  82.         mov     ax,SCREEN_WIDTH/4 ;point to the start of the first
  83.         mul     cx              ; scan line on which to draw
  84.         add     ax,[_CurrentPageBase] ;offset of first line
  85.         mov     dx,ax           ;ES:DX points to first scan line to
  86.                                 ; draw
  87.         mov     ah,byte ptr [bp+Color] ;color with which to fill
  88. FillLoop:
  89.         push    bx              ;remember line list location
  90.         push    dx              ;remember offset of start of line
  91.         push    si              ;remember # of lines to draw
  92.         mov     di,[bx+XStart]  ;left edge of fill on this line
  93.         cmp     di,[_ClipMinX]  ;clipped to left edge?
  94.         jge     MinXNotClipped  ;no
  95.         mov     di,[_ClipMinX]  ;yes, clip to the left edge
  96. MinXNotClipped:
  97.         mov     si,di
  98.         mov     cx,[bx+XEnd]    ;right edge of fill
  99.         cmp     cx,[_ClipMaxX]  ;clipped to right edge?
  100.         jl      MaxXNotClipped  ;no
  101.         mov     cx,[_ClipMaxX]  ;yes, clip to the right edge
  102.         dec     cx
  103. MaxXNotClipped:
  104.         cmp     cx,di
  105.         jl      LineFillDone    ;skip if negative width
  106.         shr     di,1    ;X/4 = offset of first rect pixel in scan
  107.         shr     di,1    ; line
  108.         add     di,dx   ;offset of first rect pixel in display mem
  109.         mov     dx,si   ;XStart
  110.         and     si,0003h                ;look up left edge plane mask
  111.         mov     bh,LeftClipPlaneMask[si] ; to clip & put in BH
  112.         mov     si,cx
  113.         and     si,0003h                  ;look up right edge plane
  114.         mov     bl,RightClipPlaneMask[si] ; mask to clip & put in BL
  115.         and     dx,not 011b     ;calculate # of addresses across rect
  116.         sub     cx,dx
  117.         shr     cx,1
  118.         shr     cx,1    ;# of addresses across rectangle to fill - 1
  119.         jnz     MasksSet ;there's more than one byte to draw
  120.         and     bh,bl   ;there's only one byte, so combine the left
  121.                         ; and right edge clip masks
  122. MasksSet:
  123.         mov     dx,SC_INDEX+1 ;already points to the Map Mask reg
  124. FillRowsLoop:
  125.         mov     al,bh   ;put left-edge clip mask in AL
  126.         out     dx,al   ;set the left-edge plane (clip) mask
  127.         mov     al,ah   ;put color in AL
  128.         stosb           ;draw the left edge
  129.         dec     cx      ;count off left edge byte
  130.         js      FillLoopBottom ;that's the only byte
  131.         jz      DoRightEdge ;there are only two bytes
  132.         mov     al,00fh ;middle addresses are drawn 4 pixels at a pop
  133.         out     dx,al   ;set the middle pixel mask to no clip
  134.         mov     al,ah   ;put color in AL
  135.         rep     stosb   ;draw the middle addresses four pixels apiece
  136. DoRightEdge:
  137.         mov     al,bl   ;put right-edge clip mask in AL
  138.         out     dx,al   ;set the right-edge plane (clip) mask
  139.         mov     al,ah   ;put color in AL
  140.         stosb           ;draw the right edge
  141. FillLoopBottom:
  142. LineFillDone:
  143.         pop     si              ;retrieve # of lines to draw
  144.         pop     dx              ;retrieve offset of start of line
  145.         pop     bx              ;retrieve line list location
  146.         add     dx,SCREEN_WIDTH/4 ;point to start of next line
  147.         add     bx,size HLine   ;point to the next line descriptor
  148.         dec     si              ;count down lines
  149.         jnz     FillLoop
  150. FillDone:
  151.         pop     di              ;restore caller's register variables
  152.         pop     si
  153.         pop     bp              ;restore caller's stack frame
  154.         ret
  155. _DrawHorizontalLineList endp
  156.         end
  157.